/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package hyperbeam.Figuras;
import hyperbeam.Estructuras.*;
import java.util.ArrayList;

/**
 *
 * @author Programmer
 */
public abstract class Figura {
    final double invalid = -1000000;
    public String idMaterial;
    public String idBumpmap;
    public String idTexture;
    public double tMin;
    public abstract ArrayList<Double> obtenerInterseccion(Punto3D camara, Vector rayo, Punto3D interseccion);
    public abstract Vector obtenerNormal    (Punto3D puntoInterseccion);
    public abstract Vector obtenerReflexion (Punto3D camara, Vector rayo, Punto3D punto);
    public abstract Vector obtenerRefraccion(Punto3D camara, Vector rayo, Punto3D punto);

    /**
     * Getter y Setter del ID del material
     * @return
     */

    public boolean hayInterseccion(){
       return (this.tMin !=  invalid);
    }

    public double getMinimaDistancia(){
        return tMin;
    }

    public String getIdMaterial() {
        return idMaterial;
    }

    public void setIdMaterial(String idMaterial) {
        this.idMaterial = idMaterial;
    }

    public String getIdBumpmap() {
        return idBumpmap;
    }

    public void setIdBumpmap(String idBumpmap) {
        this.idBumpmap = idBumpmap;
    }

    public String getIdTexture() {
        return idTexture;
    }

    public void setIdTexture(String idTexture) {
        this.idTexture = idTexture;
    }


    /**
     * Dado un vector y un ancla y una determinada distancia se obtiene el punto de interseccio
     * @param camara
     * @param rayo
     * @param distancia
     * @return
     */
    public Punto3D obtenerPuntoInterseccion(Punto3D camara, Vector rayo, double distancia){
        Punto3D punto = new Punto3D();
        punto.setX(camara.getX()+ distancia * rayo.getX());
        punto.setY(camara.getY()+ distancia * rayo.getY());
        punto.setZ(camara.getZ()+ distancia * rayo.getZ());
        punto.setW(1);
        return punto;
    }

    /**
     * Obtene el menor de los puntos de una lista de soluciones que sea mayor a cero, si no existe tal lo invalida
     * @param camara
     * @param rayo
     * @param intersecciones
     * @return
     */
    public Punto3D obtenerIntersecccionEcuacion(Punto3D camara, Vector rayo, ArrayList<Double> intersecciones){
        Punto3D interseccion = new Punto3D();
        //No hay intersecciones
        if(intersecciones.isEmpty()){
            interseccion.setInvalido();
        }
        else{
        //Solo hay una solución
            if (intersecciones.size() == 1){
                double valor = intersecciones.get(0);
                if(valor < 0.0){interseccion.setInvalido(); tMin = invalid;}
                else{           interseccion = this.obtenerPuntoInterseccion(camara, rayo,valor); tMin = valor;}
            }
            //Dos intersecciones
            else{
                double valor1, valor2;
                valor1 = intersecciones.get(0);
                valor2 = intersecciones.get(1);

                if(valor1 < 0.0 && valor2 < 0.0){interseccion.setInvalido(); tMin = invalid;}
                else if (valor1 < 0.0){ interseccion = this.obtenerPuntoInterseccion(camara, rayo,valor2); tMin = valor2;}
                else if (valor2 < 0.0){ interseccion = this.obtenerPuntoInterseccion(camara, rayo,valor1); tMin = valor1;}
                else{   double min = Math.min(valor1, valor2); interseccion = this.obtenerPuntoInterseccion(camara, rayo,min); tMin = min;}
            } 
        }
        return interseccion;
    }
}
